package org.example.myleet.rosalind.wfmd;

import org.example.myleet.rosalind.utils.BigNumberOperator;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;

public class Solution {
    public static void main(String[] args) {
        int N = 4;
        int m = 6;
        int g = 2;
        int k = 1;
        int n = 2 * N;
        int mr = n - m;
        BigDecimal pr = BigDecimal.valueOf(mr).divide(BigDecimal.valueOf(n), 10, RoundingMode.HALF_UP);
        BigDecimal pd = BigDecimal.ONE.subtract(pr);
        //计算第一代的概率，按二项式随机变量的方式计算C(m, n) * pr ^ i * pd ^ (n - i)每一中隐性基因数量的可能性，其结果是一个[x=1~2N]的数组储存每一种隐性基因数量的可能性
        BigDecimal[] prevGenRecessivePr = new BigDecimal[n + 1];
        for (int i = 1; i <= n; ++i) {
            BigDecimal p = BigNumberOperator.factorial(pr, i).multiply(BigNumberOperator.factorial(pd, n - i));
            p = p.multiply(BigDecimal.valueOf(BigNumberOperator.combination(n, i).longValue()));
            prevGenRecessivePr[i] = p;
        }
        for (int gen = 2; gen <= g; ++gen) {
            BigDecimal[] curGenRecessivePr = new BigDecimal[n + 1];
            for (int j = 1; j <= n; ++j) {
                //从第二代开始，每一代进行新的阴性基因数量可能性数组的计算
                BigInteger combination = BigNumberOperator.combination(n, j);
                //每一种阴性基因数量j的可能性 = sum(只有1个阴性基因情况下产生j个阴性基因的可能性，只有2个阴性基因情况下产生j个阴性基因的可能性，......，只有2N个阴性基因情况下产生j个阴性基因的可能性)
                BigDecimal pSum = BigDecimal.ZERO;
                for (int x = 1; x <= n; ++x) {
                    pr = BigDecimal.valueOf(x).divide(BigDecimal.valueOf(n), 10, RoundingMode.HALF_UP);
                    pd = BigDecimal.ONE.subtract(pr);
                    BigDecimal p = BigNumberOperator.factorial(pr, j).multiply(BigNumberOperator.factorial(pd, n - j));
                    p = p.multiply(BigDecimal.valueOf(combination.longValue()));
                    //prevGenRecessivePr[x]是只有x个阴性基因的情况的可能性
                    pSum = pSum.add(p.multiply(prevGenRecessivePr[x]));
                }
                curGenRecessivePr[j] = pSum;
            }
            prevGenRecessivePr = curGenRecessivePr;
        }
        BigDecimal answer = BigDecimal.ZERO;
        for (int i = k; i <= n; ++i) {
            //将至少有k个隐性基因的情况的可能性加起来
            answer = answer.add(prevGenRecessivePr[i]);
        }
        System.out.println(answer);
    }
}
